Skip to content
lab components / Forms and input

Radios

Radios allow users to choose only one item from a list of mutually exclusive choices.

This is a Lab component!

That means it doesn't satisfy our definition of done and may be changed or even deleted. For an exact status, please reach out to the Fancy team through the dev_fancy or ux_fancy channels.

import { Radios } from "@siteimprove/fancylab";

#Examples

Radios are always used in groups, and each option is represented by one Radios.Radio in the group.

  • Default state:

    one option is selected in a radio group by default. If you click on another option, the current option will be deselected.
  • Disabled state:

    indicates that an option exists but is not available in a particular case. The disabled state can be used to indicate that an option may be available again at a later time. If possible, provide hint text or a visual clue to explain why the option is disabled to avoid user confusion.
  • Label with dynamic text:

    pay attention to how the labels change in size and how the visual elements surrounding them are affected.
  • Label with icon or tooltip:

    help the user understand the context of the option.
const [radioValue, setRadioValue] = useState("option-1"); return ( <Radios // Radios must be labeled via aria if no visible label is provided (i.e. via FormElementWrapper) aria-label="An example option group" value={radioValue} onChange={setRadioValue} > <Radios.Radio value="option-1">Regular option</Radios.Radio> <Radios.Radio value="option-2" disabled> Disabled option </Radios.Radio> <Radios.Radio value="option-3"> <Icon> <IconApprove /> </Icon> <InlineText>Option with left icon</InlineText> </Radios.Radio> <Radios.Radio value="option-4"> {(props: { checked: boolean; disabled: boolean }) => ( <> <InlineText emphasis={props.checked ? "medium" : "normal"} lineHeight="multi-line" tone={props.disabled ? "subtle" : undefined} > Option with right icon and dynamic text style </InlineText> <Icon> <IconApprove /> </Icon> </> )} </Radios.Radio> <Tooltip variant={{ type: "interactive" }} content="Extra info on the option 5"> <Radios.Radio value="option-5">Option with tooltip</Radios.Radio> </Tooltip> </Radios> );

#Properties

PropertyDescriptionDefinedValue
valueRequired
objectValue of the form control
onChangeRequired
functionCallback for onChange event
nameOptional
stringName applied to the form control
idOptional
stringId applied to the form control
invalidOptional
booleanIs the form control invalid
onBlurOptional
functionCallback for onBlur event
aria-labelOptional
stringLabel of the form control
aria-describedbyOptional
stringID of an an element that describes what the form control is for
aria-labelledbyOptional
stringID of an an element that labels this form control
childrenOptional
element
directionOptional
"horizontal" | "vertical"
data-observe-keyOptional
stringUnique string, used by external script e.g. for event tracking
classNameOptional
stringCustom className that's applied to the outermost element (only intended for special cases)
styleOptional
objectStyle object to apply custom inline styles (only intended for special cases)

#Guidelines

#Best practices

#General

Use Radios when

  • the user is only allowed to select one option from a list of related items.
  • the user must see all options and compare the available options before making a choice.
  • suggesting options for the user. By making suggestions in the form of Radios instead of text entry fields or other types of input, we make it easier for the user.

#Options

  • At least two options are required in a list. Limit the number of options to seven or fewer to reduce the cognitive load on users.
  • The options are mutually exclusive, i.e. only one option can be selected at a time. Each label should be both comprehensive and unambiguous. For example, "small, medium and large" are mutually exclusive. While "small, medium, large, medium/large" are not mutually exclusive.
  • A logical order should be followed for the list of options, e.g. from most likely to least likely choice, from simplest to most complex, or from least to highest risk.
  • Provide a default selection or a recommended radio selection to assist the user. A default selection helps in situations where the options are complex or unfamiliar to the user.
  • Add a “None” option when the user does not have an appropriate answer.
  • Add an “Other” option if the user has an answer that is not included in a list.

#Placement

Radios are typically used in the following places:

  • Forms

    Radios can be used in cards, modals, side panels, and forms on full pages. They can often serve as a filtering mechanism. An example of a radio in a form can be found in Customise New Share Widget.
  • Settings

    Radios can be used to create new settings or change settings in a menu or widget. An example of radios in settings can be found in Create Survey.

#Style

  • Arrange the radios vertically to make it easier for users to compare options, especially in forms and settings. If only horizontal layouts are an option, arrange the radios and labels so that it is absolutely clear which option belongs to which label.

#Do not use when

  • the user can choose more than one item from a list. In this case, use a Checkbox instead.
  • the user needs to toggle items on or off with an immediate effect. In this case, use a Toggle Switch instead.
  • a list has more than seven options. In this case, use a Select instead.
  • the user can toggle between two or more alternate views of the same content. In this case, use a Toggle Group instead.

#Accessibility

For designers

  • If possible, always provide a visible label for Radios. Alternatively, provide an aria-label to describe the purpose of Radios.
  • Use Radios instead of Select components whenever possible. When you use radios, users who have difficulty making precise mouse movements can select an item more easily. When you use a select component, the user has to click on a button element to see a list of options or an action menu.
  • Allow users to select an item by clicking on its label to make it easier to select the item.
  • Radios should always be placed to the left of their labels. This makes Radios easier to find, especially for screen magnifier users.

For developers

Assistive technologies, like screen readers, require that each radio button and its surrounding group have a programmatically accessible label. This label can be provided through a visible <label>, aria-label, aria-labelledby, or similar attribute.

Explore detailed guidelines for this component: Accessibility Specifications

#Writing

  • It is recommended that the label contains three words or less.
  • Use clear and concise labels.
  • Use sentence case for a label.
  • Do not include punctuation after a label.
  • Users cannot be assumed to know the number of options they can choose based on the visual difference between checkboxes and radios. Provide a hint text that indicates only one option should be selected from a list of radios. For example: “Select one option.”
  • If an answer is required, add a "(required)" text or an asterisk "(*)" after a group label.
  • Do not forget to include choices. The example below does not include 18.
    • Under 18
    • Over 18

#Notable changes

#Migrating from FancyLab 16.x to FancyLab 17.x

The Radios component on FancyLab 16.x or prior takes an array of control objects as input/property, which is terse and works well with typechecking, but it plays poorly with composition. As an example, adding a tooltip to a radio label is not possible using this structure as well as changing the icon position to after or before the label.

So, in FancyLab 17.x, the Radios component was refactored to allow composing other components with them. Now, instead of having a controls object, subcomponents are used to create the controls.

Please find below an example that illustrates the usage before and after these changes. Note that the controls property has been replaced by children of type Radios.Radio.

#Before

<Radios value={radioValue} onChange={setRadioValue} controls={[ { value: "option-1", label: "Option 1", }, { value: "option-2", label: "Option 2", }, { value: "option-3", label: "Option 3", }, ]} />

#After

<Radios value={radioValue} onChange={setRadioValue}> <Radios.Radio value="option-1">Option 1</Radios.Radio> <Radios.Radio value="option-2">Option 2</Radios.Radio> <Radios.Radio value="option-3">Option 3</Radios.Radio> </Radios>